#include "HttpServer.hpp"
#include "err.hpp"
#include "Util.hpp"
#include <vector>

const std::string SEP = "\r\n";
const std::string webRoot = "wwwroot";                  // web根目录
const std::string defaultHomePage = "index.html";       // 默认首页
const std::string page_404 = "./wwwroot/err_404.html";  // 404页面

class HttpRequest
{
public:
    HttpRequest()
        : path_(webRoot)
    {
    }

    void Print()
    {
        logMessage(Debug, "method: %s, url: %s, version: %s", method_.c_str(), url_.c_str(), httpVersion_.c_str());
        logMessage(Debug, "path: %s", path_.c_str());
        logMessage(Debug, "suffix: %s", suffix_.c_str());

    }
    ~HttpRequest() {}

public:
    std::string method_;
    std::string url_;
    std::string httpVersion_;
    std::vector<std::string> body_;
    std::string path_;
    std::string suffix_;                //后缀
};

// 反序列化
HttpRequest Deserialize(std::string &message)
{
    HttpRequest req;
    std::string line = Util::ReadLine(message, SEP);
    Util::ParseRequestLine(line, &req.method_, &req.url_, &req.httpVersion_);

    while (!message.empty())
    {
        line = Util::ReadLine(message, SEP);
        req.body_.push_back(line);
    }
    req.path_ += req.url_;
    if (req.path_[req.path_.size() - 1] == '/') // 如果访问默认目录，则改为访问默认首页
    {
        req.path_ += defaultHomePage;
    }

    // 根据后缀判断文件类型，没找到就默认为html类型，判断后填充到后缀中
    auto pos = req.path_.rfind(".");
    if(pos == std::string::npos)
    {
        req.suffix_ == ".html";
    }
    else
    {
        req.suffix_ = req.path_.substr(pos);
    }
    return req;
}

// 根据URL中的文件后缀添加文件类型报头  [Content-Type]: [XXX.XXX]
std::string GetContentType(const std::string& suffix)
{
    std::string content_type = "Content-Type: ";
    if (suffix == ".html" || suffix == ".htm")
        content_type + "text/html";
    else if (suffix == ".css")
        content_type += "text/css";
    else if (suffix == ".js")
        content_type += "application/x-javascript";
    else if (suffix == ".png")
        content_type += "image/png";
    else if (suffix == ".jpg")
        content_type += "image/jpeg";
    else if (suffix == ".gif")
        content_type += "image/gif";
    else
    {
        // ...
    }
    return content_type + SEP;
}

// 用于数据处理的回调函数
std::string HandlerHttp(std::string &httpRequest)
{
    // 打印接收到的序列化请求
    std::cout << "-------------------------------------------------" << std::endl;
    std::cout << httpRequest << std::endl;


    // 将获取到的请求反序列化
    HttpRequest req = Deserialize(httpRequest);
    req.Print();

    // 根据反序列化后的请求从文件中读取有效载荷
    std::string body;
    Util::ReadFile(req.path_, &body);

    // 添加响应信息
    std::string response = "HTTP/1.0 200 OK" + SEP;                     // 添加状态行
    response += "Contene-Lenght: " + std::to_string(body.size()) + SEP; // 添加响应报头中的数据长度
    response += GetContentType(req.suffix_);                            // 根据后缀添加响应报头中的数据类型
    response += SEP;                                                    // 添加空行
    response += body;                                                   // 添加有效载荷

    return response;
}



void usage(std::string proc)
{
    std::cout << "Usage:\n\t" << proc << " ip\n" << std::endl;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = std::atoi(argv[1]);
    std::unique_ptr<HttpServer> tsvr(new HttpServer(HandlerHttp, port));
    tsvr->InitServer();
    tsvr->Start();

    return 0;
}